﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;

using FCNS.Native;
using FCNS.Utility;

namespace FCNS.KeepMoney.UI
{
    /// <summary>
    /// 自定义 <see cref="ListView"/> 控件
    /// </summary>
	public sealed class ListViewEx :ListView
	{
        /// <summary>
        /// 构造函数
        /// </summary>
		public ListViewEx() : base()
		{
			try { this.DoubleBuffered = true; }
			catch(Exception) { Debug.Assert(false); }
		}
        /// <summary>
        /// 引发 System.Windows.Forms.Control.KeyDown 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.KeyEventArgs。</param>
		protected override void OnKeyDown(KeyEventArgs e)
		{
			try { if(SkipGroupHeaderIfRequired(e)) return; }
			catch(Exception) { Debug.Assert(false); }

			base.OnKeyDown(e);
		}

		private bool SkipGroupHeaderIfRequired(KeyEventArgs e)
		{
			if(!this.ShowGroups) return false;
			if(this.MultiSelect) return false;

			ListViewItem lvi = this.FocusedItem;
			if(lvi != null)
			{
				ListViewGroup g = lvi.Group;
				ListViewItem lviChangeTo = null;

				if((e.KeyCode == Keys.Up) && IsFirstLastItemInGroup(g, lvi, true))
					lviChangeTo = (GetNextLvi(g, true) ?? lvi); // '??' for top item
				else if((e.KeyCode == Keys.Down) && IsFirstLastItemInGroup(g, lvi, false))
					lviChangeTo = (GetNextLvi(g, false) ?? lvi); // '??' for bottom item

				if(lviChangeTo != null)
				{
					foreach(ListViewItem lviEnum in this.Items)
						lviEnum.Selected = false;

					lviChangeTo.Selected = true;
					lviChangeTo.Focused = true;
					EnsureVisible(lviChangeTo.Index);

					e.Handled = true;
					return true;
				}
			}

			return false;
		}

		private static bool IsFirstLastItemInGroup(ListViewGroup g,
			ListViewItem lvi, bool bFirst)
		{
			if(g == null) { Debug.Assert(false); return false; }

			ListViewItemCollection c = g.Items;
			if(c.Count == 0) { Debug.Assert(false); return false; }

			return (bFirst ? (c[0] == lvi) : (c[c.Count - 1] == lvi));
		}

		private ListViewItem GetNextLvi(ListViewGroup gBaseExcl, bool bUp)
		{
			if(gBaseExcl == null) { Debug.Assert(false); return null; }

			int i = this.Groups.IndexOf(gBaseExcl);
			if(i < 0) { Debug.Assert(false); return null; }

			if(bUp)
			{
				--i;
				while(i >= 0)
				{
					ListViewGroup g = this.Groups[i];
					if(g.Items.Count > 0) return g.Items[g.Items.Count - 1];

					--i;
				}
			}
			else // Down
			{
				++i;
				int nGroups = this.Groups.Count;
				while(i < nGroups)
				{
					ListViewGroup g = this.Groups[i];
					if(g.Items.Count > 0) return g.Items[0];

					++i;
				}
			}

			return null;
		}
	}
}
